package com.iqiyi.pps.epg.api.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iqiyi.kiwi.utils.Configuration;
import com.iqiyi.mams.hedvig.rpc.client.ServiceHelper;
import com.iqiyi.pps.epg.api.entity.CrossData;
import com.iqiyi.pps.epg.api.model.web.channel.TChannelLog;
import com.iqiyi.pps.epg.api.model.web.program.TProgramDirectorLog;
import com.iqiyi.pps.epg.api.model.web.program.TProgramLog;
import com.iqiyi.pps.epg.api.model.web.ticket.TTicketLog;
import com.iqiyi.pps.epg.api.model.web.vod.TVodLog;
import com.iqiyi.pps.epg.api.server.web.broadcast.BroadcastControlWebService;
import com.iqiyi.pps.epg.api.server.web.carousel.CarouselWebService;
import com.iqiyi.pps.epg.api.server.web.channel.ChannelWebService;
import com.iqiyi.pps.epg.api.server.web.encode.EncodeServerWebService;
import com.iqiyi.pps.epg.api.server.web.news.NewsWebService;
import com.iqiyi.pps.epg.api.server.web.program.ProgramDirectorWebService;
import com.iqiyi.pps.epg.api.server.web.program.ProgramWebService;
import com.iqiyi.pps.epg.api.server.web.record.RecordWebService;
import com.iqiyi.pps.epg.api.server.web.record.RecordColRpcService;
import com.iqiyi.pps.epg.api.server.web.statistic.StatisticWebService;
import com.iqiyi.pps.epg.api.server.web.stream.ChannelStreamWebService;
import com.iqiyi.pps.epg.api.server.web.stream.LiveStreamWebService;
import com.iqiyi.pps.epg.api.server.web.ticket.TicketWebService;
import com.iqiyi.pps.epg.api.server.web.vod.VodWebService;
import org.apache.commons.lang.StringUtils;
import org.apache.thrift.TBase;
import org.apache.thrift.TException;
import org.apache.thrift.TSerializer;
import org.apache.thrift.protocol.TSimpleJSONProtocol;
import org.jboss.netty.channel.ChannelConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriInfo;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by karkarrotxu on 2016/9/9.
 */
public final class ServiceUtil {


    private static Logger logger = LoggerFactory.getLogger(ServiceUtil.class);

    private ServiceUtil() {
    }

    ;

    public static final Map<String, String> KEYS_MAP = new HashMap() {{
        put("boss", "fy6qGaAT5xurJzNf");
        put("lego", "NLxJRrdyFZ9Tawd2");
        put("frontend", "7dpHGKMy4hAh3DmC");
    }};
    public static final int RESERVATION_INTERVAL_MILLISECONDS = 600000;
    public static final boolean DEV_MODE_FLAG = Boolean.valueOf(Configuration.getString("qipu.entity.devMode"));
    public static final String ERROR_CLIENT_TIME = "客户端时间不正确（应该为准确时间前后五分钟范围内），授权失败";
    public static final String ERROR_EXIST = "出现异常";
    public static final String INTERFACE_ERROR = "接口异常";
    public static final String AUTH_FAIL = "授权失败";
    public static final String PARAMETER_ERROR = "参数错误";
    public static final String NO_EXECUTE_RULE_ERROR = "无可执行规则";
    public static final String EXECUTE_RULE_RUNNING_ERROR = "规则已经在执行中";
    public static final String FORBIDDEN_ADD_RULE_ERROR = "规则执行中不允许添加";

    public static Map<String, String> formatApiLogMap(String strParam, UriInfo uriInfo, HttpHeaders httpHeaders) {
        String serverIp = getServerIp();
        Map<String, String> map = new HashMap<String, String>();
        map.put("typeId", "1");
        map.put("name", "/" + uriInfo.getPath());
        map.put("serverIp", serverIp);
        map.put("reqTime", String.valueOf(System.currentTimeMillis()));
        map.put("appkey", getHeaderParameter("From", httpHeaders));
        map.put("params", strParam);
        return map;
    }

    public static String getServerIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getHeaderParameter(String name, HttpHeaders httpHeaders) {
        if (httpHeaders.getRequestHeader(name) != null) {
            return httpHeaders.getRequestHeader(name).get(0);
        }
        return null;
    }

    public static void insertInterfaceLog(Map<String, String> logData) {
        try {
            ChannelWebService.Iface logInstance = getChannelService();
            if (logInstance == null) {
                logger.info("logInstance empty");
                return;
            }
            logInstance.saveApiLog(JSON.toJSONString(logData));
        } catch (Exception e) {
            logger.error("[insertInterfaceLog][Error]", e);
        }
    }

    public static String checkAuthorizationResponse(HttpHeaders httpHeaders, UriInfo uriInfo) {
        int authorResult = checkAuthorization(httpHeaders, uriInfo);
        if (authorResult == 2) {
            return Constants.getJsonResponse(Constants.CODE_ERROR_AUTH, null, ERROR_CLIENT_TIME);
        } else if (authorResult != 0) {
            return Constants.getJsonResponse(Constants.CODE_ERROR_AUTH, null, AUTH_FAIL);
        }
        return null;
    }

    public static int checkAuthorization(HttpHeaders httpHeaders, UriInfo uriInfo) {
        try {
            String sign = httpHeaders.getRequestHeader("Sign").get(0);
            // 万能密钥
            if (sign.equals("#f93Uc31K24()_@")) {
                return 0;
            }

            String time = httpHeaders.getRequestHeader("Time").get(0);
            if (StringUtils.isEmpty(sign) || StringUtils.isEmpty(time)) {
                return 1;
            }

            String userName = SsoUtil.getSsoUsername(httpHeaders);
            if (StringUtils.isBlank(userName)) {
                return 1;
            }
            // 5分钟内请求有效
            long now = System.currentTimeMillis();
            if (Math.abs(Long.valueOf(time) * 1000 - now) > 300000) {
                logger.error("[checkAuthorization][Time={}][now={}][msg=Time error][userName={}]", time, now, userName);
                return 2;
            }

            String from = getHeaderParameter("From", httpHeaders);
            if (!KEYS_MAP.containsKey(from)) {
                logger.error("[checkAuthorization][From={}][msg=From error]", from);
                return 1;
            }


            String md5 = MD5Util.MD5("/" + uriInfo.getPath() + time + KEYS_MAP.get(from));
            if (sign.equalsIgnoreCase(md5)) {
                return 0;
            }
            logger.error("[checkAuthorization][Sign={}][md5={}][msg=Sign error]", sign, md5);

            return 1;
        } catch (Exception e) {
            return 1;
        }
    }

    public static String getResponseError(String msg) {
        return Constants.getJsonResponse(Constants.CODE_ERROR, null, msg);
    }

    public static String getResponseFail(String msg) {
        return Constants.getJsonResponse(Constants.CODE_FAIL, null, msg);
    }

    public static String getResponseError() {
        return getResponseError("请求异常");
    }

//    public static String getOpUser() {
//        CrossData crossData = CrossDataLocalPool.get();
//        return SsoUtil.getSsoUsername(crossData.getHttpHeaders());
//    }

    private static ProgramWebService.Iface pService = null;

    public static synchronized ProgramWebService.Iface getProgramService() {
        if (pService == null) {
            pService = ServiceHelper.getThriftService(ProgramWebService.Iface.class);
        }
        return pService;
    }

    private static ChannelWebService.Iface cService = null;

    public static synchronized ChannelWebService.Iface getChannelService() {
        if (cService == null) {
            cService = ServiceHelper.getThriftService(ChannelWebService.Iface.class);
            logger.info("[ChannelWebService is null] = {}", (cService == null));
        }
        return cService;
    }

    private static CarouselWebService.Iface carouselService = null;

    public static synchronized CarouselWebService.Iface getCarouselService() {
        if (carouselService == null) {
            carouselService = ServiceHelper.getThriftService(CarouselWebService.Iface.class);
        }
        return carouselService;
    }

    private static StatisticWebService.Iface sService = null;

    public static synchronized StatisticWebService.Iface getStatisticService() {
        if (sService == null) {
            sService = ServiceHelper.getThriftService(StatisticWebService.Iface.class);
        }
        return sService;
    }

    private static BroadcastControlWebService.Iface bService = null;

    public static synchronized BroadcastControlWebService.Iface getBroadcastService() {
        if (bService == null) {
            bService = ServiceHelper.getThriftService(BroadcastControlWebService.Iface.class);
        }
        return bService;
    }

    private static ChannelStreamWebService.Iface cswService = null;

    public static synchronized ChannelStreamWebService.Iface getChannelStreamWebService() {
        if (cswService == null) {
            cswService = ServiceHelper.getThriftService(ChannelStreamWebService.Iface.class);
        }
        return cswService;
    }

    private static EncodeServerWebService.Iface eService = null;

    public static synchronized EncodeServerWebService.Iface getEncodeServerService() {
        if (eService == null) {
            eService = ServiceHelper.getThriftService(EncodeServerWebService.Iface.class);
        }
        return eService;
    }

    private static LiveStreamWebService.Iface lService = null;

    public static synchronized LiveStreamWebService.Iface getLiveStreamService() {
        if (lService == null) {
            lService = ServiceHelper.getThriftService(LiveStreamWebService.Iface.class);
        }
        return lService;
    }

    private static ProgramDirectorWebService.Iface pdwService = null;

    public static synchronized ProgramDirectorWebService.Iface getpdwService() {
        if (pdwService == null) {
            pdwService = ServiceHelper.getThriftService(ProgramDirectorWebService.Iface.class);
        }
        return pdwService;
    }

    private static NewsWebService.Iface newsService = null;

    public static synchronized NewsWebService.Iface getNewsService() {
        if (newsService == null) {
            newsService = ServiceHelper.getThriftService(NewsWebService.Iface.class);
        }
        return newsService;
    }

    private static VodWebService.Iface vodService = null;

    public static synchronized VodWebService.Iface getVodWebService() {
        if (vodService == null) {
            vodService = ServiceHelper.getThriftService(VodWebService.Iface.class);
        }
        return vodService;
    }

    private static TicketWebService.Iface ticketWebService = null;

    public static synchronized TicketWebService.Iface getTicketWebService() {
        if (ticketWebService == null) {
            ticketWebService = ServiceHelper.getThriftService(TicketWebService.Iface.class);
        }
        return ticketWebService;
    }

    private static RecordColRpcService.Iface recordColRpcService = null;
    public static synchronized RecordColRpcService.Iface getRecordColRpcService(){
        if (recordColRpcService == null) {
            recordColRpcService = ServiceHelper.getThriftService(RecordColRpcService.Iface.class);
        }
        return recordColRpcService;
    }

    private static RecordWebService.Iface recordWebService = null;
    public static synchronized RecordWebService.Iface getRecordWebService() {
        if (recordWebService == null) {
            recordWebService = ServiceHelper.getThriftService(RecordWebService.Iface.class);
        }
        return recordWebService;
    }

    /**
     * 写频道日志
     *
     * @param channelId
     * @param type
     * @param user
     * @param descr
     */
    public static void writeChannelLog(long channelId, int type, String user, String descr) {
        try {
            ChannelWebService.Iface channelService = getChannelService();
            if (channelService == null) {
                logger.error("fail find service: [channelId={}][type={}][user={}][descr={}]", channelId, type, user, descr);
                return;
            }
            TChannelLog tChannelLog = new TChannelLog();
            tChannelLog.setFatherId(channelId);
            tChannelLog.setType(type);

            if (user == null || user.equals("") || user.equals("0")) {
                String httpUser = getOpUser();
                tChannelLog.setUser(httpUser == null ? Constants.SYSTEM_USER_SIGN : httpUser);
            } else {
                tChannelLog.setUser(user);
            }
            tChannelLog.setDescr(descr);
            boolean saveSuc = channelService.saveLog(tChannelLog);
            logger.info("writeProgramLog[channelId={}][type={}][suc={}]", channelId, type, saveSuc);
        } catch (Exception e) {
            logger.info("[BasementApiServiceImpl][writeChannelLog][exception=]", e);
        }
    }

    /**
     * 写节目日志
     *
     * @param pid
     * @param type
     * @param user
     * @param descr
     */
    public static void writeProgramLog(long pid, int type, String user, String descr) {
        try {
            ProgramWebService.Iface programService = getProgramService();
            if (programService == null) {
                logger.error("fail find service: [programId={}][type={}][user={}][descr={}]", pid, type, user, descr);
                return;
            }
            TProgramLog tProgramLog = new TProgramLog();
            tProgramLog.setProgramId(pid);
            tProgramLog.setType(type);

            if (user == null || user.equals("") || user.equals("0")) {
                String httpUser = getOpUser();
                tProgramLog.setUser(httpUser == null ? Constants.SYSTEM_USER_SIGN : httpUser);
            } else {
                tProgramLog.setUser(user);
            }
            tProgramLog.setDescr(descr);
            boolean saveSuc = programService.saveProgramLog(tProgramLog);
            logger.info("writeProgramLog[programId={}][type={}][suc={}]", pid, type, saveSuc);
        } catch (Exception e) {
            logger.info("[writeProgramLog][exception=]", e);
        }
    }

    /**
     * 写导播台日志
     *
     * @param directorId
     * @param type
     * @param user
     * @param descr
     */
    public static void writeDirectorLog(int directorId, int type, String user, String descr) {
        try {
            ProgramDirectorWebService.Iface service = getpdwService();
            if (service == null) {
                logger.error("fail find service: [directorId={}][type={}][user={}][descr={}]", directorId, type, user, descr);
                return;
            }
            TProgramDirectorLog tProgramDirectorLog = new TProgramDirectorLog();
            if (user == null || user.equals("") || user.equals("0")) {
                String httpUser = getOpUser();
                tProgramDirectorLog.setUser(httpUser == null ? Constants.SYSTEM_USER_SIGN : httpUser);
            } else {
                tProgramDirectorLog.setUser(user);
            }
            tProgramDirectorLog.setDirectorId(directorId);
            tProgramDirectorLog.setType(type);
            tProgramDirectorLog.setDescr(descr);
            boolean saveSuc = service.saveLog(tProgramDirectorLog);
            logger.info("writeDirectorLog[programId={}][type={}][suc={}]", directorId, type, saveSuc);
        } catch (Exception e) {
            logger.info("[writeDirectorLog][exception=]", e);
        }
    }

    /**
     * 写直转点日志
     *
     * @param channelId
     * @param type
     * @param user
     * @param descr
     */
    public static void writeVodLog(int channelId, int type, String user, String descr) {
        try {
            VodWebService.Iface service = getVodWebService();
            if (service == null) {
                logger.error("fail find service: [channelId={}][type={}][user={}][descr={}]", channelId, type, user, descr);
                return;
            }
            TVodLog tVodLog = new TVodLog();
            if (user == null || user.equals("") || user.equals("0")) {
                String httpUser = getOpUser();
                tVodLog.setUser(httpUser == null ? Constants.SYSTEM_USER_SIGN : httpUser);
            } else {
                tVodLog.setUser(user);
            }
            tVodLog.setChannelId(channelId);
            tVodLog.setType(type);
            tVodLog.setDescr(descr);
            long tVodLogId = service.saveLog(tVodLog);
            logger.info("writeDirectorLog[channelId={}][type={}][suc={}]", channelId, type, tVodLogId > 0);
        } catch (Exception e) {
            logger.info("[writeDirectorLog][exception=]", e);
        }
    }


    /**
     * 写工单日志
     *
     * @param dataId
     * @param type
     * @param user
     * @param descr
     */
    public static void writeTicketLog(long dataId, int type, String user, String descr) {
        try {
            TicketWebService.Iface ticketWebService1 = getTicketWebService();
            if (ticketWebService1 == null) {
                logger.error("fail find service: [programId={}][type={}][user={}][descr={}]", dataId, type, user, descr);
                return;
            }
            TTicketLog ticketLog = new TTicketLog();
            ticketLog.setDataId(dataId);
            ticketLog.setType(type);

            if (user == null || user.equals("") || user.equals("0")) {
                String httpUser = getOpUser();
                ticketLog.setUser(httpUser == null ? Constants.SYSTEM_USER_SIGN : httpUser);
            } else {
                ticketLog.setUser(user);
            }
            ticketLog.setDescr(descr);
            long logId = ticketWebService1.saveLog(ticketLog);
            logger.info("writeProgramLog[dataId={}][type={}][suc={}]", dataId, type, logId > 0);
        } catch (Exception e) {
            logger.info("[writeProgramLog][exception=]", e);
        }
    }

    public static String getOpUser() {
        CrossData crossData = CrossDataLocalPool.get();
        if (crossData == null) {
            return null;
        }
        return SsoUtil.getSsoUsername(crossData.getHttpHeaders());
    }

    public static UriInfo getUriInfo() {
        CrossData crossData = CrossDataLocalPool.get();
        if (crossData == null) {
            return null;
        }
        return crossData.getUriIfo();
    }


    /**
     * 生产相应结果对象
     *
     * @param value
     * @return
     */
    public static String transTBaseToString(Object value) {
        if (null != value) {
            Class ifaceimplClass = value.getClass();
            Class<?>[] interfaces = ifaceimplClass.getInterfaces();
            if (interfaces[0] != null && interfaces[0].getName().equals("org.apache.thrift.TBase")) {//thrift 需要特殊处理
                TSerializer serializer = new TSerializer(new TSimpleJSONProtocol.Factory());
                try {
                    String data = serializer.toString((TBase) value);
                    JSONObject jsonObject = JSON.parseObject(data, JSONObject.class);
                    return jsonObject.toString();
                } catch (TException e) {
                    e.printStackTrace();
                }
            } else {
                return value.toString();
            }
        }
        return null;
    }
}
